//! 认证消息处理器
//! 处理1100认证请求消息

use log::{debug, error};
use iso8583_rs::iso8583::iso_spec::IsoMsg;
use iso8583_rs::iso8583::IsoError;
use crate::config::{
    self, message_types, response_codes, field_numbers, business_rules
};
use crate::services::{
    ValidationService, ResponseBuilder,
    validation::{MacValidationResult, PinValidationResult}
};
use super::message_handler::{MessageHandler, MessageHandleResult};

/// 认证消息处理器
pub struct AuthHandler;

impl AuthHandler {
    pub fn new() -> Self {
        Self
    }

    /// 验证金额字段
    fn validate_amount(&self, request_msg: &IsoMsg) -> Result<u32, String> {
        if !request_msg.bmp.is_on(field_numbers::AMOUNT as u32) {
            return Err("缺少金额字段".to_string());
        }

        let amount_str = request_msg.get_field_value(&field_numbers::AMOUNT.to_string())
            .map_err(|_| "无法获取金额值")?;

        amount_str.parse::<u32>()
            .map_err(|_| "金额格式错误".to_string())
    }

    /// 处理MAC验证失败
    fn handle_mac_validation_failure(
        &self,
        request_msg: &IsoMsg,
    ) -> Result<MessageHandleResult, IsoError> {
        error!("MAC验证失败");
        let response_msg = ResponseBuilder::build_error_response(
            request_msg,
            message_types::AUTH_RESPONSE,
            response_codes::MAC_VERIFICATION_FAILED,
        )?;

        Ok(MessageHandleResult {
            response_msg,
            success: false,
        })
    }

    /// 处理金额验证失败
    fn handle_amount_validation_failure(
        &self,
        request_msg: &IsoMsg,
        error_msg: &str,
    ) -> Result<MessageHandleResult, IsoError> {
        error!("金额验证失败: {}", error_msg);
        let error_code = if error_msg.contains("缺少") {
            response_codes::MISSING_AMOUNT
        } else {
            response_codes::INVALID_AMOUNT
        };

        let response_msg = ResponseBuilder::build_error_response(
            request_msg,
            message_types::AUTH_RESPONSE,
            error_code,
        )?;

        Ok(MessageHandleResult {
            response_msg,
            success: false,
        })
    }

    /// 处理PIN验证结果
    fn apply_pin_validation_result(
        &self,
        response_msg: &mut IsoMsg,
        pin_result: PinValidationResult,
    ) -> Result<(), IsoError> {
        match pin_result {
            PinValidationResult::Invalid => {
                response_msg.set_on(field_numbers::RESPONSE_CODE as u32, response_codes::PIN_VERIFICATION_FAILED)?;
            }
            PinValidationResult::ProcessingError => {
                response_msg.set_on(field_numbers::RESPONSE_CODE as u32, response_codes::PIN_PROCESSING_ERROR)?;
            }
            _ => {} // Valid或NotPresent不需要特殊处理
        }
        Ok(())
    }
}

impl MessageHandler for AuthHandler {
    fn handle(
        &self,
        request_msg: &IsoMsg,
        raw_msg: &[u8],
        validation_service: &ValidationService,
    ) -> Result<MessageHandleResult, IsoError> {
        debug!("开始处理认证请求消息");

        // 1. 验证MAC
        let mac_result = validation_service.validate_mac(request_msg, raw_msg);
        if mac_result == MacValidationResult::Invalid {
            return self.handle_mac_validation_failure(request_msg);
        }

        // 2. 验证金额
        let amount = match self.validate_amount(request_msg) {
            Ok(amt) => {
                debug!("金额验证成功: {}", amt);
                amt
            }
            Err(error_msg) => {
                return self.handle_amount_validation_failure(request_msg, &error_msg);
            }
        };

        // 3. 构建基于金额的响应
        let mut response_msg = ResponseBuilder::build_amount_based_response(
            request_msg,
            message_types::AUTH_RESPONSE,
            amount,
        )?;

        // 4. 验证PIN（如果存在）
         let pin_result = validation_service.validate_pin(request_msg, &config::DEFAULT_PIN);
         self.apply_pin_validation_result(&mut response_msg, pin_result)?;

        debug!("认证请求处理完成");
        Ok(MessageHandleResult {
            response_msg,
            success: true,
        })
    }

    fn supported_message_type(&self) -> &'static str {
        message_types::AUTH_REQUEST
    }
}

#[cfg(test)]
mod tests {
    use super::*;
    use hex_literal::hex as hex_l;

    #[test]
    fn test_auth_handler_creation() {
        let handler = AuthHandler::new();
        assert_eq!(handler.supported_message_type(), "1100");
    }

    #[test]
    fn test_validate_amount_missing() {
        let handler = AuthHandler::new();
        // 这里需要创建一个模拟的IsoMsg来测试
        // 由于IsoMsg的复杂性，这里只是展示测试结构
    }
}